package com.hospital.ecard.module.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hospital.api.RemoteDictionaryService;
import com.hospital.common.core.module.controller.vo.PatientReqEntity;
import com.hospital.common.core.module.entity.BankMedicalCardDict;
import com.hospital.common.core.module.entity.ecard.*;
import com.hospital.common.core.result.ErrorTip;
import com.hospital.common.core.result.SuccessTip;
import com.hospital.common.core.result.Tip;
import com.hospital.common.core.utils.IdentityPlace;
import com.hospital.common.core.utils.PinYinKit;
import com.hospital.common.core.utils.RedisUtils;
import com.hospital.ecard.cardhandler.*;
import com.hospital.ecard.module.entity.PatientInfo;
import com.hospital.ecard.module.service.PatientInfoService;
import com.hospital.ecard.patienthandler.PatientInfoBindHandler;
import com.hospital.ecard.patienthandler.PatientInfoElectronicHandler;
import com.hospital.ecard.patienthandler.PatientInfoExecute;
import com.hospital.ecard.patienthandler.PatientInfoNewHandler;
import com.hospital.ecard.task.SetWorkKeyScheduled;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lvyao
 * @description card控制器
 * @date 2020/7/1
 */
@RestController
@RequestMapping("/card")
@Slf4j
public class CardController {

    @Resource
    private PatientInfoService patientInfoService;

    @Resource
    private RemoteDictionaryService remoteDictionaryService;

    /**
     * 获取院内患者基本信息
     *
     * @param requestVal
     * @param request
     * @return
     */
    @PostMapping(value = "/getInfo", produces = {"application/json;charset=UTF-8"})
    public String getRemoteInfo(@RequestBody String requestVal, HttpServletRequest request) {
//        log.info("getInfo:" + requestVal);
        BarcodeLogEntity barcodeLogEntity = JSON.parseObject(requestVal, BarcodeLogEntity.class);
        CardHandler cardHandler = null;
        if (barcodeLogEntity.getType() == 1) {
            cardHandler = new ECardHandler();
        } else if (barcodeLogEntity.getType() == 2) {
            cardHandler = new VisitCardHandler();
        } else if (barcodeLogEntity.getType() == 4) {
            cardHandler = new PatientIdHandler();
        } else if (barcodeLogEntity.getType() == 5) {
            cardHandler = new InpNoHandler();
        } else {
            cardHandler = new IdentityCardHandler();
        }
        CardHandlerStrategy cardHandlerStrategy = null;
        try {
            cardHandlerStrategy = new CardHandlerStrategy(cardHandler);
        } catch (Exception e) {
            return e.getMessage();
        }
        return cardHandlerStrategy.getInfo(barcodeLogEntity, request);
    }

    /**
     * 获取电子健康卡信息 20220409 修改
     *
     * @Param requestVal
     */
    @PostMapping(value = "/registerInfo", produces = {"application/json;charset=UTF-8"})
    public String registerInfo(@RequestBody String requestVal) {
//        log.info("registerInfo:" + requestVal);
        CardInfo cardInfo = JSON.parseObject(requestVal, CardInfo.class);
        EcardRegister ecardRegister = new EcardRegister();
        ecardRegister.setCardNo(cardInfo.getPeopleInfo().getSfzhm().toUpperCase());
        ecardRegister.setCardType("01");
        ecardRegister.setPhoneNum(cardInfo.getPeopleInfo().getBrdh());
        ecardRegister.setName(cardInfo.getPeopleInfo().getXm());
        String returnStr = "注册消息获取失败!";
        ResponseEntity<EcardRegisterResponse> returnVal = new ResponseEntity<>();
        try {
            returnStr = ECardHandler.getPersonCardByInfoNew(JSON.toJSONString(ecardRegister), "1");
            returnVal.setIsSuccess(10000);
            returnVal.setErrMsg("");
            returnVal.setBusinessInfo(JSON.parseObject(returnStr, (Type) RegisterResEntity.class));
        } catch (Exception e) {
            e.printStackTrace();
            returnVal.setErrMsg(e.getMessage());
            returnVal.setIsSuccess(10001);
        } finally {
            returnStr = JSON.toJSONString(returnVal);
            return returnStr;
        }
//        return PatientInfoHandler.getPersonCardByInfo(cardInfo);
    }

    /**
     * 20210506 更新患者基本信息整理
     * 根据院内ID、实体卡卡号绑定，以及新建
     *
     * @param patientReqEntity
     * @param bindingResult
     * @return
     */
    @PostMapping(value = "/updateInfo", produces = {"application/json;charset=UTF-8"})
    public Tip updateInfoNew(@RequestBody @Valid PatientReqEntity patientReqEntity, BindingResult bindingResult) {
//        log.info("updateInfo:" + patientReqEntity);
        StringBuilder stringBuilder = new StringBuilder();
        if (bindingResult.hasErrors()) {
            bindingResult.getAllErrors().stream().forEach(
                    c -> stringBuilder.append(c.getObjectName() + ":" + c.getDefaultMessage() + "\r\n")
            );
        }
        if (stringBuilder.length() > 0) {
            return new ErrorTip("1020", stringBuilder.toString());
        }

        PatientInfoElectronicHandler patientInfoElectronicHandler = null;
        if (patientReqEntity.getHosCardNo() != null && !patientReqEntity.getHosCardNo().equals("")) {
            patientInfoElectronicHandler = new PatientInfoBindHandler();
        } else {
            patientInfoElectronicHandler = new PatientInfoNewHandler();
        }
        PatientInfoExecute patientInfoExcute = new PatientInfoExecute(patientInfoElectronicHandler);
        PatientInfo patientInfo = null;
        try {
            patientInfo = patientInfoExcute.execute(patientReqEntity);
        } catch (Exception e) {
            return new ErrorTip("1010", e.getMessage());
        }
        return new SuccessTip(JSON.parseObject(JSONObject.toJSONString(patientInfo, SerializerFeature.WriteMapNullValue), PatientInfo.class));
    }

    /**
     * 更新患者基本信息
     *
     * @param patientReqEntity
     * @param bindingResult
     * @return
     * @throws ParseException
     */
    @PostMapping(value = "/updateInfoNew", produces = {"application/json;charset=UTF-8"})
    public Tip updateInfo(@RequestBody @Valid PatientReqEntity patientReqEntity, BindingResult bindingResult) throws ParseException {
        StringBuilder stringBuilder = new StringBuilder();
        if (bindingResult.hasErrors()) {
            bindingResult.getAllErrors().stream().forEach(
                    c -> stringBuilder.append(c.getObjectName() + ":" + c.getDefaultMessage() + "\r\n")
            );
        }
        if (stringBuilder.length() > 0) {
            return new ErrorTip("1020", stringBuilder.toString());
        }

        boolean isNewRecord = false;
        boolean isUpdate = false;
        if (patientReqEntity.getHosCardNo() != null && !patientReqEntity.getHosCardNo().equals("")) {
            try {
                List<String> patientNames = patientInfoService.seLectPatientName(patientReqEntity.getHosCardNo());
                List<String> patientIdno = patientInfoService.selectPatientIdno(patientReqEntity.getHosCardNo());
                if (patientNames == null || patientNames.size() > 1) {
                     return new ErrorTip("1006", "未查询到患者姓名或该就诊卡号名下有多个患者姓名！");
                } else {
                    if (!patientNames.get(0).trim().equals(patientReqEntity.getPatientName().trim())) {
                         return new ErrorTip("1007", "填写患者姓名与该就诊卡号名下患者姓名不符或身份证不符！");
                    }
                    if (patientIdno.get(0) != null && !patientIdno.get(0).trim().toUpperCase().equals(patientReqEntity.getIdNo().toUpperCase())) {
                        return new ErrorTip("1010", "查询就诊卡号名下患者身份证号与填写身份证号不符，请到窗口核实！");
                    }
                }
            } catch (Exception e) {
                return new ErrorTip("1008", "根据患者ID或就诊卡卡号获取不到患者基本信息！");
            }

        }
        List<PatientInfo> patientInfoList = patientInfoService.selectPatientInfoByIdNo(patientReqEntity.getIdNo());
        PatientInfo patientInfo = null;
        PatientInfo patientInfo1 = null;
        List<PatientInfo> patientInfoArrayList = new ArrayList<>();
        List<PatientInfo> patientInfos1 = new ArrayList<>();
        if ((patientInfoList != null && patientInfoList.size() > 0)) {
            if (patientReqEntity.getHosCardNo() != null && !patientReqEntity.getHosCardNo().isEmpty()) {
                patientInfoArrayList = patientInfoList.stream().filter(c -> patientReqEntity.getHosCardNo().equals(c.getCardId()) && "5".equals(c.getCardStatus())).collect(Collectors.toList());
                if (patientInfoArrayList.size() > 1) {
                    return new ErrorTip("1004", "该就诊卡所属院内ID有多个请到窗口查询处理！");
                } else if (patientInfoArrayList.size() == 0) {
                    patientInfo1 = patientInfoList.stream().filter(c -> patientReqEntity.getHosCardNo().equals(c.getPatientId()) || patientReqEntity.getHosCardNo().equals(c.getCardId())).findFirst().orElse(null);
                    if (patientReqEntity.getHosCardNo() != null && !patientReqEntity.getHosCardNo().equals("")) {
                        if (patientInfo1 == null || (patientInfo1 != null && patientReqEntity.getHosCardNo().length() < 9 ? !patientInfo1.getPatientId().equals(patientReqEntity.getHosCardNo()) : patientInfo1 != null && patientInfo1.getCardId() != null && !patientInfo1.getCardId().equals(patientReqEntity.getHosCardNo()))) {
                            patientInfo1 = patientInfoService.selectPatientInfoByIdNo(patientReqEntity.getHosCardNo()).get(0);
                            patientInfo1.setIdNo(patientReqEntity.getIdNo());
                        }
                    }
                } else {
                    patientInfo1 = patientInfoArrayList.get(0);
                }
            }
            List<PatientInfo> patientInfos = patientInfoList.stream().filter(c -> c.getHealthCardId() != null).collect(Collectors.toList());
            if (patientInfos != null && patientInfos.size() > 0) {
                String patId;
                if (patientInfos.size() > 1 && patientInfo1 != null) {
                    patId = patientInfo1.getPatientId();
                    patientInfos1 = patientInfos.stream().filter(c -> c.getPatientId() != patId).collect(Collectors.toList());
                    patientInfo = patientInfos.stream().filter(c -> c.getPatientId() == patId).findFirst().orElse(patientInfo1);
                } else {
                    patientInfo = patientInfos.get(0);
                    patId = patientInfo.getPatientId();
                    if (patientInfos.size() > 1) {
                        patientInfos1 = patientInfos.stream().filter(c -> c.getPatientId() != patId).collect(Collectors.toList());
                    }
                }
            } else if (!patientReqEntity.getHosCardNo().equals("") && patientReqEntity.getHosCardNo().length() < 9) {
                patientInfo = patientInfoService.selectPatientInfoByIdNo(patientReqEntity.getHosCardNo()).get(0);
                patientInfos1 = patientInfoService.selectPatientInfoByIdNo(patientReqEntity.getHealthCardId()).stream().filter(c -> !c.getPatientId().equals(patientReqEntity.getHosCardNo())).collect(Collectors.toList());
            } else {
                if (patientReqEntity.getHosCardNo() != null && !patientReqEntity.getHosCardNo().equals("")) {
                    patientInfo = patientInfoList.stream().filter(c -> c.getPatientId().equals(patientReqEntity.getHosCardNo()) || (c.getCardId() != null && c.getCardId().equals(patientReqEntity.getHosCardNo()))).collect(Collectors.toList()).get(0);
                } else {
                    patientInfo = patientInfoList.get(0);
                }
            }
            if (!patientInfo.getName().trim().equals(patientReqEntity.getPatientName().trim())) {
                return new ErrorTip("1005", "院内已注册患者姓名与填写姓名不符！");
            }
            if (patientInfo1 != null && patientInfo.getPatientId() != patientInfo1.getPatientId()) {
                isUpdate = true;
                PatientInfo temp = null;
                temp = patientInfo1;
                patientInfo1 = patientInfo;
                patientInfo = temp;
                patientInfo1.setHealthCardId("");
                patientInfo1.setPHid("");
                patientInfo1.setQrCodeText("");
                patientInfo1.setAdminExt("");
            }
        } else {
            if (patientReqEntity.getHosCardNo() != null && !patientReqEntity.getHosCardNo().equals("")) {
                patientInfo = patientInfoService.selectPatientInfoByIdNo(patientReqEntity.getHosCardNo()).get(0);
                patientInfo.setIdNo(patientReqEntity.getIdNo());
                patientInfos1 = patientInfoService.selectPatientInfoByIdNo(patientReqEntity.getHealthCardId()).stream().filter(c -> !c.getPatientId().equals(patientReqEntity.getHosCardNo())).collect(Collectors.toList());
            } else {
                isNewRecord = true;
                patientInfo = new PatientInfo();
                BeanUtils.copyProperties(patientReqEntity, patientInfo);
                patientInfo.setName(patientReqEntity.getPatientName());
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String s = sdf.format(patientReqEntity.getBirthDay());
                patientInfo.setDateOfBirth(sdf.parse(s));
                patientInfo.setPhoneNumberHome(patientReqEntity.getPhone());
                if ("1,3".contains(patientReqEntity.getCreateChannel()) && patientReqEntity.getTerminal() != null && !patientReqEntity.getTerminal().equals("")) {
                    if ("3".equals(patientReqEntity.getCreateChannel())) {
                        BankMedicalCardDict bankMedicalCardDict = remoteDictionaryService.getbankMedicalCardDictList().stream().filter(bankMedicalCardDict1 -> bankMedicalCardDict1.getTerminal().equals(patientReqEntity.getTerminal())).findFirst().orElse(null);
                        if (bankMedicalCardDict != null) {
                            patientInfo.setOperator(bankMedicalCardDict.getUserId());
                            int maxPid = Integer.parseInt(bankMedicalCardDict.getMaxPatientId()) + 1;
                            String patientId = bankMedicalCardDict.getBankMachineCode() + String.format("%06d", maxPid);
                            patientInfo.setPatientId(patientId);
                            bankMedicalCardDict.setMaxPatientId(String.format("%06d", maxPid));
                            remoteDictionaryService.updateDtoMedicalCardDictUpdate(bankMedicalCardDict);
                        } else {
                            throw new RuntimeException("自助机配置表中未找到该设备配置信息");
                        }
                    } else {
                        patientInfo.setOperator(patientReqEntity.getTerminal());
                    }
                } else {
                    patientInfo.setOperator("9271");
                }
                if (patientInfo.getPatientId() == null) {
                    String patientId = patientInfoService.getPatientId();
                    if (patientId != null) {
                        patientInfo.setPatientId(patientId);
                    } else {
                        throw new RuntimeException("获取patientId失败");
                    }
                }
                boolean lb = true;
                Calendar today = Calendar.getInstance();
                Calendar birthday = Calendar.getInstance();
                today.setTime(new Date());
                birthday.setTime(patientReqEntity.getBirthDay());
                int year = today.get(Calendar.YEAR) - birthday.get(Calendar.YEAR);
                int month = today.get(Calendar.MONTH) - birthday.get(Calendar.MONTH);
                int day = today.get(Calendar.DATE) - birthday.get(Calendar.DATE);
                if (year < 65) {
                    lb = false;
                } else if (year == 65) {
                    if (month <= 0) {
                        if (month < 0) {
                            lb = false;
                        } else {
                            if (day <= 0) {
                                if (day < 0) {
                                    lb = false;
                                }
                            }
                        }
                    }
                }
                if (lb) {
                    patientInfo.setChargeType("寿星优惠");
                }
                patientInfo.setMailingAddress(patientReqEntity.getAddress());
                patientInfo.setBirthPlace(patientReqEntity.getIdNo().substring(0, 6));
            }
        }
        if (patientInfo.getNamePhonetic() == null) {
            String pinY = PinYinKit.getHanziInitials(patientInfo.getName());
            patientInfo.setNamePhonetic(pinY.replace(':', ' ').toUpperCase());
        }
        if (patientInfo.getMailingAddress() == null) {
            if (patientReqEntity.getState() != null && patientReqEntity.getCity() != null && patientReqEntity.getAddress() != null) {
                patientInfo.setMailingAddress(patientReqEntity.getState() + patientReqEntity.getCity() + patientReqEntity.getAddress());
            }
        }
        if (patientInfo.getPhoneNumberHome() != null && patientReqEntity.getPhone() != null && !patientReqEntity.getPhone().isEmpty() && patientInfo.getPhoneNumberHome() != patientReqEntity.getPhone()) {
            patientInfo.setPhoneNumberHome(patientReqEntity.getPhone());
        }
        if (patientReqEntity.getPhid() != null) {
            patientInfo.setPHid(patientReqEntity.getPhid());
        }
        if (patientReqEntity.getQrCodeText() != null) {
            patientInfo.setQrCodeText(patientReqEntity.getQrCodeText());
        }
        if (patientReqEntity.getAdminExt() != null) {
            patientInfo.setAdminExt(patientReqEntity.getAdminExt());
        }
        if (patientReqEntity.getHealthCardId() != null) {
            patientInfo.setHealthCardId(patientReqEntity.getHealthCardId());
        }
        if (StringUtils.isEmpty(patientInfo.getState()) || StringUtils.isEmpty(patientInfo.getCity()) || StringUtils.isEmpty(patientInfo.getDistrict())) {
            String s = patientReqEntity.getIdNo().substring(0, 6);
            String stateString = IdentityPlace.getProvince(Integer.parseInt(s));
            int length = stateString.length();
            patientInfo.setState(length > 5 ? stateString.substring(0, 5) : stateString);
            patientInfo.setCity(IdentityPlace.getCity(Integer.parseInt(s)));
            patientInfo.setDistrict(IdentityPlace.getDistrict(Integer.parseInt(s)));
        }
        if (StringUtils.isEmpty(patientInfo.getAddress())) {
            patientInfo.setAddress(patientReqEntity.getAddress());
        }
        if (isNewRecord) {
            patientInfoService.save(patientInfo);
        } else {
            if (isUpdate) {
                patientInfoService.updateById(patientInfo1);
            }
            if (patientInfos1 != null && patientInfos1.size() > 0) {
                for (PatientInfo patientInfo2 : patientInfos1) {
                    patientInfo2.setHealthCardId("");
                    patientInfo2.setPHid("");
                    patientInfo2.setQrCodeText("");
                    patientInfo2.setAdminExt("");
                    patientInfoService.updateById(patientInfo2);
                }
            }
            patientInfoService.updateById(patientInfo);
        }

        return new SuccessTip(JSON.parseObject(JSONObject.toJSONString(patientInfo, SerializerFeature.WriteMapNullValue), PatientInfo.class), isNewRecord ? 1 : 0);
    }

    /**
     * 注册电子健康卡信息通过WEBAPI
     *
     * @Param requestVal
     */
    @PostMapping(value = "/registerInfoNew", produces = {"application/json;charset=UTF-8"})
    public String registerInfoNew(@RequestBody String requestVal) {
        EcardRegister cardInfo = JSON.parseObject(requestVal, EcardRegister.class);
        String returnStr = "注册消息获取失败!";
        try {
            returnStr = ECardHandler.getPersonCardByInfoNew(JSON.toJSONString(cardInfo), "1");
        } catch (Exception e) {
            e.printStackTrace();
            returnStr = e.getMessage();
        } finally {
            return returnStr;
        }
    }

    /**
     * 根据二维码获取电子健康卡信息通过WEBAPI
     *
     * @Param requestVal
     */
    @PostMapping(value = "/getInfoNew", produces = {"application/json;charset=UTF-8"})
    public String getInfoNew(@RequestBody String requestVal) {
        EcardQRcodeInfo cardInfo = JSON.parseObject(requestVal, EcardQRcodeInfo.class);
        String returnStr = "根据二维码获取电子健康卡信息失败!";
        try {
            returnStr = ECardHandler.getPersonCardByInfoNew(JSON.toJSONString(cardInfo), "2");
        } catch (Exception e) {
            e.printStackTrace();
            returnStr = e.getMessage();
        } finally {
            return returnStr;
        }
    }

//    @GetMapping (value = "/test")
//    public ResultInfo testNew(){
//        StopWatch stopWatch = new StopWatch();
//        stopWatch.start();
//        patientInfoService.selectPatientInfoByIdNo("10061113");
//        stopWatch.stop();
//        log.info("ID号查询：" +stopWatch.getTotalTimeSeconds());
//
//
//        StopWatch stopWatch1 = new StopWatch();
//        stopWatch1.start();
//        patientInfoService.selecttest("10061113");
//        stopWatch1.stop();
//        log.info("ID号查询union：" +stopWatch1.getTotalTimeSeconds());
//
//
//        StopWatch stopWatch2 = new StopWatch();
//        stopWatch2.start();
//        patientInfoService.selectPatientInfoByIdNo("610302199408013563");
//        stopWatch2.stop();
//        log.info("身份证号查询：" +stopWatch2.getTotalTimeSeconds());
//
//
//        StopWatch stopWatch3 = new StopWatch();
//        stopWatch3.start();
//        patientInfoService.selecttest("610302199408013563");
//        stopWatch3.stop();
//        log.info("身份证号查询union：" +stopWatch3.getTotalTimeSeconds());
//
//
//        StopWatch stopWatch4 = new StopWatch();
//        stopWatch4.start();
//        patientInfoService.selectPatientInfoByIdNo("9000000526");
//        stopWatch4.stop();
//        log.info("卡号查询：" +stopWatch4.getTotalTimeSeconds());
//
//
//        StopWatch stopWatch5 = new StopWatch();
//        stopWatch5.start();
//        patientInfoService.selecttest("9000000526");
//        stopWatch5.stop();
//        log.info("卡号查询union：" +stopWatch5.getTotalTimeSeconds());
//
//
//        StopWatch stopWatch6 = new StopWatch();
//        stopWatch6.start();
//        patientInfoService.selectPatientInfoByIdNo("61A650B08B7DFE8AFEB1274EBD8E2CD20E51595B0B515DD1618FA18E117CC281");
//        stopWatch6.stop();
//        log.info("健康卡号查询：" +stopWatch6.getTotalTimeSeconds());
//
//
//        StopWatch stopWatch7 = new StopWatch();
//        stopWatch7.start();
//        patientInfoService.selecttest("61A650B08B7DFE8AFEB1274EBD8E2CD20E51595B0B515DD1618FA18E117CC281");
//        stopWatch7.stop();
//        log.info("健康卡号查询union：" +stopWatch7.getTotalTimeSeconds());
//        return null;
//    }

    /**
     * 手动设置redis密钥
     *
     * @Param requestVal
     */
    @GetMapping(value = "/setWorkKey")
    public String setWorkKey() {
        String authKeyStr = SetWorkKeyScheduled.setWorkKey();
        if (RedisUtils.isExistsKey("workKey")) {
            String workKey = RedisUtils.getKey("workKey");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("getRedisWorkKey", workKey);
            jsonObject.put("getScheduledWorkKey", authKeyStr);
            return jsonObject.toJSONString();
        }
        return "仅获取方法返回WorkKey：" + authKeyStr + "设置Redis失败！";
    }


    /**
     * 手动设置redis密钥
     *
     * @Param requestVal
     * @return
     */
    @GetMapping(value = "/getPatientInfo")
    public PatientInfo getPatientInfo(String patientId) {
        return patientInfoService.getById(patientId);
    }

}
